package com.linqi.freebie.http.ktorClientCio.request

import com.linqi.freebie.http.ktorClientCio.HttpClientManager
import com.linqi.freebie.http.ktorClientCio.response.HttpError
import com.linqi.freebie.http.ktorClientCio.response.ResponseHolder
import com.linqi.freebie.http.ktorClientCio.response.XResult
import com.linqi.freebie.utils.JsonUtils
import io.github.aakira.napier.Napier
import io.ktor.client.HttpClient
import io.ktor.client.plugins.ClientRequestException
import io.ktor.client.plugins.RedirectResponseException
import io.ktor.client.plugins.ServerResponseException
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.bodyAsText
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import java.io.InterruptedIOException
import java.net.ConnectException
import java.net.UnknownHostException
import kotlin.coroutines.cancellation.CancellationException

object RequestCore {
    private val SUCCESS_RANGE = 200..299
    private val json = Json {
        ignoreUnknownKeys = true
        isLenient = true
    }

    /**
     * 通用请求执行器（使用KSerializer）
     */
    suspend fun <T : Any> request(
        serializer: KSerializer<T>,
        isInfoResponse: Boolean = true,
        call: suspend (HttpClient) -> HttpResponse
    ): ResponseHolder<T> {
        val client = HttpClientManager.getClient()
        try {
            val response = call(client)
            return parseResponse(response, serializer, isInfoResponse)
        } catch (cause: Throwable) {
            return ResponseHolder.Error(catchException(cause))
        }
    }

    /**
     * 解析HttpResponse（使用KSerializer）
     */
    private suspend fun <T : Any> parseResponse(
        response: HttpResponse,
        serializer: KSerializer<T>,
        isInfoResponse: Boolean //非标准返回值 不是定制的Json格式  或者  XML格式等。。
    ): ResponseHolder<T> {
        return try {
            when {
                response.status.value !in SUCCESS_RANGE -> resolveFailedResponse(response)
                isInfoResponse -> resolveInfoResponse(response, serializer)
                else -> resolveUnInfoResponse(response, serializer)
            }
        } catch (cause: Throwable) {
            ResponseHolder.Error(catchException(cause).apply {
                httpCode = response.status.value
            })
        }
    }

    /**
     * 处理标准响应结构
     */
    private suspend fun <T : Any> resolveInfoResponse(
        response: HttpResponse,
        serializer: KSerializer<T>
    ): ResponseHolder<T> {
        val result =  JsonUtils.fromJson(XResult.Companion.serializer(serializer),response.bodyAsText())
        return if (result.isSuccessful()) {
            ResponseHolder.Success(result.data)
        } else {
            ResponseHolder.Failure(result.code, result.msg)
        }
    }

    /**
     * 处理非标准响应结构
     *  单独处理数据，不进行解析
     *  非标准返回值 不是定制的Json格式  或者  XML格式等。。
     */
    private suspend fun <T : Any> resolveUnInfoResponse(
        response: HttpResponse,
        serializer: KSerializer<T>
    ): ResponseHolder<T> {
        val data = response.bodyAsText()
        @Suppress("UNCHECKED_CAST")
        return ResponseHolder.Success(data) as ResponseHolder<T>
    }

    /**
     * 处理失败响应
     *
     */
    private suspend fun resolveFailedResponse(response: HttpResponse): ResponseHolder<Nothing> {
        return try {
            val errorResult = json.decodeFromString<XResult<Nothing>>(response.bodyAsText())
            ResponseHolder.Failure(errorResult.code, errorResult.msg)
        } catch (e: Exception) {
            ResponseHolder.Failure(
                response.status.value.toString(),
                response.bodyAsText()
            )
        }
    }

    /**
     * 异常处理（保持不变）
     */
    private fun catchException(cause: Throwable): HttpError {
        return when (cause) {
            is ConnectException, is UnknownHostException -> HttpError(
                errorCode = HttpError.Companion.CONNECT_ERROR,
                errorMsg = "服务器连接失败, 请检查网络连接",
                cause = cause
            )
            is InterruptedIOException -> HttpError(
                errorCode = HttpError.Companion.CONNECT_TIMEOUT,
                errorMsg = "网络请求超时",
                cause = cause
            )
            is ClientRequestException,
            is ServerResponseException,
            is RedirectResponseException -> HttpError(
                errorCode = HttpError.Companion.BAD_NETWORK,
                errorMsg = "网络请求错误: ${cause.message}",
                cause = cause
            )
            is SerializationException,
            is ClassCastException -> HttpError(
                errorCode = HttpError.Companion.PARSE_ERROR,
                errorMsg = "数据解析失败",
                cause = cause
            )
            is CancellationException -> HttpError(
                errorCode = HttpError.Companion.CANCEL_REQUEST,
                errorMsg = "请求已取消",
                cause = cause
            )
            else -> HttpError(
                errorCode = HttpError.Companion.UNKNOW_ERROR,
                errorMsg = cause.localizedMessage ?: "未知错误",
                cause = cause
            )
        }
    }
}